package com.hsgene.user.service.impl;

import com.hsgene.common.DeleteFlagType;
import com.hsgene.common.util.basic.UUID32;
import com.hsgene.common.util.result.ApiResult;
import com.hsgene.common.util.result.NullObject;
import com.hsgene.common.util.security.MD5Utils;
import com.hsgene.common.util.support.LimitHelper;
import com.hsgene.common.util.support.OrderHelper;
import com.hsgene.common.util.support.Pagination;
import com.hsgene.common.util.validation.FieldChecker;
import com.hsgene.common.util.web.session.UserInfo;
import com.hsgene.user.domain.Company;
import com.hsgene.user.domain.Department;
import com.hsgene.user.dto.orginazation.CompanyDto;
import com.hsgene.user.dto.orginazation.DepartmentDto;
import com.hsgene.user.dto.orginazation.OrganizationDto;
import com.hsgene.user.condition.OperationAccountCondition;
import com.hsgene.user.condition.OperationAccountOrderField;
import com.hsgene.user.constants.CustomerSourceType;
import com.hsgene.user.converter.UserConverter;
import com.hsgene.user.domain.GeneticTestingOperationAccount;
import com.hsgene.user.dto.user.GeneticTestingUserDto;
import com.hsgene.user.exception.OrganizationErrorCode;
import com.hsgene.user.exception.UserErrorCode;
import com.hsgene.user.persistence.CompanyRepository;
import com.hsgene.user.persistence.DepartmentRepository;
import com.hsgene.user.persistence.OperationAccountRepository;
import com.hsgene.user.service.CompanyService;
import com.hsgene.user.service.DepartmentService;
import com.hsgene.user.service.OperationAccountService;
import com.hsgene.user.service.OperationOrganizationService;
import com.hsgene.user.session.UserSessionComponent;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * 后台管理用户ServiceImpl
 *
 * @author wangbing
 * @version 1.0, 2018/11/2
 */
@Service
public class OperationAccountServiceImpl implements OperationAccountService {

    private final static Logger LOGGER = LoggerFactory.getLogger(OperationAccountServiceImpl.class);
    public static final String AGENECY_NAEM = "检测机构";

    @Resource
    private OperationAccountRepository operationAccountRepository;

    @Resource
    private OperationOrganizationService operationOrganizationService;

    @Resource
    private UserSessionComponent userSessionComponent;

    @Value("${user.password.default}")
    private String defaultUserPassword;
    @Resource
    private CompanyService companyService;
    @Resource
    private DepartmentService departmentService;
    @Resource
    private CompanyRepository companyRepository;
    @Resource
    private DepartmentRepository departmentRepository;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<NullObject> addOperationAccount(GeneticTestingOperationAccount operationAccount) {
        FieldChecker.checkEmpty(operationAccount, "用户信息");
        operationAccount.check();

        // 校验用户是否已存在
        GeneticTestingOperationAccount existed = operationAccountRepository.findByPhone(operationAccount.getPhone());
        if (existed != null) {
            if (DeleteFlagType.DELETE.getCode() == existed.getDeleteFlag()) {
                return ApiResult.fail(UserErrorCode.USER_DELETED);
            }
            return ApiResult.fail(UserErrorCode.USER_EXISTED);
        }
        existed = operationAccountRepository.findByName(operationAccount.getName());
        if (existed != null) {
            if (DeleteFlagType.DELETE.getCode() == existed.getDeleteFlag()) {
                return ApiResult.fail(UserErrorCode.USER_DELETED);
            }
            return ApiResult.fail(UserErrorCode.USER_EXISTED);
        }
        existed = operationAccountRepository.findByRealName(operationAccount.getRealName());
        if (existed != null) {
            if (DeleteFlagType.DELETE.getCode() == existed.getDeleteFlag()) {
                return ApiResult.fail(UserErrorCode.USER_DELETED);
            }
            return ApiResult.fail(UserErrorCode.USER_EXISTED);
        }
        // 补充查询校验用户公司部门职位等信息
        String orgId = operationAccount.getPositionId();
        String orgType = "position";
        if (StringUtils.isBlank(orgId)) {
            orgId = operationAccount.getDepartmentId();
            orgType = "department";
        }
        ApiResult<OrganizationDto> orgResult = operationOrganizationService.findOrganization(orgId, orgType);
        if (!orgResult.isSucc()) {
            return ApiResult.fail(orgResult.getError());
        }
        OrganizationDto org = orgResult.getData();
        // 用户不存在，可以添加新用户，补充用户信息
        operationAccount.setId(UUID32.randomUUIDString());
        operationAccount.setPassword(MD5Utils.getMD5Code(defaultUserPassword));
        operationAccount.setCreateDateTime(new Date());
        operationAccount.setUpdateDateTime(operationAccount.getCreateDateTime());
        operationAccount.setDeleteFlag(DeleteFlagType.NOT_DELETED.getCode());
        operationAccount.setPositionId(org.getPositionId());
        operationAccount.setPositionName(org.getPositionName());
        operationAccount.setDepartmentId(org.getDepartmentId());
        operationAccount.setDepartmentName(org.getDepartmentName());
        operationAccount.setCompanyId(org.getCompanyId());
        operationAccount.setCompanyName(org.getCompanyName());
        operationAccountRepository.save(operationAccount);

        return ApiResult.succ();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<NullObject> updateOperationAccountPwd(String id, String newPwd, boolean isFirstLoginInit) {
        FieldChecker.checkMinMaxLength(newPwd, 4, 16, "密码");
        GeneticTestingOperationAccount account = operationAccountRepository.findById(id);
        if (account == null) {
            return ApiResult.fail(UserErrorCode.USER_NOT_EXISTED);
        }
        if (DeleteFlagType.DELETE.getCode() == account.getDeleteFlag()) {
            return ApiResult.fail(UserErrorCode.USER_DELETED);
        }
        newPwd = MD5Utils.getMD5Code(newPwd);
        if (isFirstLoginInit && account.getPassword().equals(newPwd)) {
            return ApiResult.fail(UserErrorCode.PASSWORD_SAME);
        }
        account.setPassword(newPwd);
        account.setUpdateDateTime(new Date());
        if (isFirstLoginInit) {
            account.setLatestLoginDateTime(account.getUpdateDateTime());
        }
        operationAccountRepository.update(account);
        return ApiResult.succ();
    }

    @Override
    public ApiResult<Pagination<GeneticTestingOperationAccount>> queryOperationAccounts(
            OperationAccountCondition condition, OrderHelper orderHelper, LimitHelper limitHelper) {
        FieldChecker.checkEmpty(limitHelper, "分页参数");
        if (orderHelper != null) {
            orderHelper.validate(OperationAccountOrderField.getInstance());
        }

        int totalCount = operationAccountRepository.queryCount(condition);
        Pagination<GeneticTestingOperationAccount> pagination = Pagination.newInstance(limitHelper, totalCount);
        if (totalCount > 0 && limitHelper.getOffset() <= totalCount) {
            List<GeneticTestingOperationAccount> result = operationAccountRepository.queryAccounts(condition, orderHelper, limitHelper);
            if (!CollectionUtils.isEmpty(result)) {
                int number = limitHelper.getOffset() + 1;
                for (GeneticTestingOperationAccount account : result) {
                    account.setNumber(number++);
                    account.setPassword(null);
                }
            }
            pagination.setResult(result);
        }
        return ApiResult.succ(pagination);
    }

    @Override
    public ApiResult<GeneticTestingOperationAccount> findOperationAccount(String accountId) {
        FieldChecker.checkEmpty(accountId, "accountId");

        GeneticTestingOperationAccount account = operationAccountRepository.findById(accountId);
        if (account == null) {
            return ApiResult.fail(UserErrorCode.USER_NOT_EXISTED);
        }
        if (DeleteFlagType.DELETE.getCode() == account.getDeleteFlag()) {
            return ApiResult.fail(UserErrorCode.USER_DELETED);
        }
        account.setPassword(null);

        return ApiResult.succ(account);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<NullObject> updateOperationAccount(GeneticTestingOperationAccount operationAccount) {
        FieldChecker.checkEmpty(operationAccount, "用户信息");
        operationAccount.check(false);

        GeneticTestingOperationAccount account = operationAccountRepository.findById(operationAccount.getId());
        if (account == null || account.getSystemSuper()) {
            return ApiResult.fail(UserErrorCode.USER_NOT_EXISTED);
        }
        // 校验用户是否已存在
        GeneticTestingOperationAccount existed = operationAccountRepository.findByPhone(operationAccount.getPhone());
        if (existed != null && !existed.getId().equals(operationAccount.getId())) {
            return ApiResult.fail(UserErrorCode.USER_EXISTED);
        }
        existed = operationAccountRepository.findByName(operationAccount.getName());
        if (existed != null && !existed.getId().equals(operationAccount.getId())) {
            return ApiResult.fail(UserErrorCode.USER_EXISTED);
        }
        existed = operationAccountRepository.findByRealName(operationAccount.getRealName());
        if (existed != null && !existed.getId().equals(operationAccount.getId())) {
            return ApiResult.fail(UserErrorCode.USER_EXISTED);
        }
        // 补充查询校验用户公司部门职位等信息
        String orgId = operationAccount.getPositionId();
        String orgType = "position";
        if (StringUtils.isBlank(orgId)) {
            orgId = operationAccount.getDepartmentId();
            orgType = "department";
        }
        ApiResult<OrganizationDto> orgResult = operationOrganizationService.findOrganization(orgId, orgType);
        if (!orgResult.isSucc()) {
            return ApiResult.fail(orgResult.getError());
        }
        OrganizationDto org = orgResult.getData();
        account.setUpdateDateTime(new Date());
        account.setDeleteFlag(DeleteFlagType.NOT_DELETED.getCode());
        account.setPositionId(org.getPositionId());
        account.setPositionName(org.getPositionName());
        account.setDepartmentId(org.getDepartmentId());
        account.setDepartmentName(org.getDepartmentName());
        account.setCompanyId(org.getCompanyId());
        account.setCompanyName(org.getCompanyName());
        account.setGender(operationAccount.getGender());
        account.setPhone(operationAccount.getPhone());
        account.setName(operationAccount.getName());
        operationAccountRepository.update(account);
        // 被修改用户正处于登录状态时，更新用户缓存信息
        GeneticTestingUserDto userDto = UserConverter.toGeneticTestingUserDto(account);
        UserInfo userInfo = UserConverter.buildUserInfo(userDto, CustomerSourceType.WEB_CONSOLE);
        boolean refreshed = userSessionComponent.refreshUserInfo(userInfo);
        if (refreshed) {
            LOGGER.info("用户{}正在登录，身份信息已被刷新");
        } else {
            LOGGER.info("用户{}未登录，不需要刷新身份信息");
        }

        return ApiResult.succ();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<NullObject> deleteOperationAccount(String accountId) {
        FieldChecker.checkEmpty(accountId, "accountId");

        GeneticTestingOperationAccount account = operationAccountRepository.findById(accountId);
        if (account == null) {
            return ApiResult.fail(UserErrorCode.USER_NOT_EXISTED);
        }
        if (DeleteFlagType.DELETE.getCode() == account.getDeleteFlag()) {
            return ApiResult.succ();
        }
        account.setDeleteFlag(DeleteFlagType.DELETE.getCode());
        account.setUpdateDateTime(new Date());
        operationAccountRepository.update(account);
        // 如果被删除用户正处于登录状态，强制用户下线
        GeneticTestingUserDto userDto = UserConverter.toGeneticTestingUserDto(account);
        UserInfo userInfo = UserConverter.buildUserInfo(userDto, CustomerSourceType.WEB_CONSOLE);
        userSessionComponent.remove(null, userInfo);

        return ApiResult.succ();
    }

    @Override
    public ApiResult<NullObject> validateDuplicationAccount(Integer type, String field, String excludeUserId) {
        if (1 == type) {
            return validateAccountRealName(field, excludeUserId);
        } else if (2 == type) {
            return validateAccountPhone(field, excludeUserId);
        } else {
            return ApiResult.succ();
        }
    }

    @Override
    public ApiResult<NullObject> addAgencyAccount(GeneticTestingOperationAccount operationAccount) {
        // 补充查询校验用户公司部门职位等信息
        int i = companyService.queryCompanyCountByName(AGENECY_NAEM);
        if(i<=0){
            return  ApiResult.fail(OrganizationErrorCode.TESTING_AGENCY_COMPANY_DOES_NOT_EXIST);
        }else{
            Company company= companyRepository.queryCompanyByName(AGENECY_NAEM);
            Department department=departmentRepository.queryByName(AGENECY_NAEM,company.getId());
            if(department==null){
                return ApiResult.fail(OrganizationErrorCode.THE_DETECTION_MECHANISM_PART_DOES_NOT_EXIST);
            }else{
                Date date = new Date();
                operationAccount.setCreateDateTime(date);
                operationAccount.setUpdateDateTime(date);
                operationAccount.setDepartmentId(department.getId());
                operationAccount.setDepartmentName(department.getDepartmentName());
                operationAccount.setCompanyName(company.getCompanyName());
                operationAccount.setCompanyId(operationAccount.getCompanyId());
                operationAccount.setPassword(MD5Utils.getMD5Code(defaultUserPassword));
                operationAccount.setDeleteFlag(DeleteFlagType.NOT_DELETED.getCode());
            }
        }
        operationAccountRepository.save(operationAccount);
        return ApiResult.succ();
    }

    @Override
    public ApiResult<NullObject> updateAgencyAccount(GeneticTestingOperationAccount account) {
        operationAccountRepository.updateAgencyAccount(account);
        return ApiResult.succ();
    }

    private ApiResult<NullObject> validateAccountPhone(String phone, String excludeUserId) {
        GeneticTestingOperationAccount existed = operationAccountRepository.findByPhone(phone);
        if (existed != null && !existed.getId().equals(excludeUserId)) {
            if (DeleteFlagType.DELETE.getCode() == existed.getDeleteFlag()) {
                return ApiResult.fail(UserErrorCode.USER_DELETED);
            }
            return ApiResult.fail(UserErrorCode.USER_EXISTED);
        }
        return ApiResult.succ();
    }

    private ApiResult<NullObject> validateAccountRealName(String realName, String excludeUserId) {
        GeneticTestingOperationAccount existed = operationAccountRepository.findByRealName(realName);
        if (existed != null && !existed.getId().equals(excludeUserId)) {
            if (DeleteFlagType.DELETE.getCode() == existed.getDeleteFlag()) {
                return ApiResult.fail(UserErrorCode.USER_DELETED);
            }
            return ApiResult.fail(UserErrorCode.USER_EXISTED);
        }
        return ApiResult.succ();
    }
}
